package com.eunion.core.common.jpa;

import java.io.Serializable;
import java.util.List;
import java.util.Optional;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.transaction.annotation.Transactional;

import com.eunion.core.common.jpa.query.BasicDelete;
import com.eunion.core.common.jpa.query.FindByKeyQueryRequirement;
import com.eunion.core.common.jpa.query.QueryRequirement;
import com.eunion.core.common.jpa.query.QuickFilterQueryRequirement;

public interface ProjectionQueryExecutor<Entity, Bean> {

    Entity load(Serializable id);

    Optional<Bean> findOne(QueryRequirement<Entity, Bean> req);

    List<Bean> findAll(QueryRequirement<Entity, Bean> req);

    List<Bean> findAll(QueryRequirement<Entity, Bean> req, Sort sort);

    Page<Bean> findAll(QueryRequirement<Entity, Bean> req, Pageable pageable);

    default Optional<Bean> findByKey(FindByKeyQueryRequirement<Entity, Bean> req) {
        return findOne(req);
    }

    default List<Bean> quickFilter(QuickFilterQueryRequirement<Entity, Bean> req) {
        return findAll(req);
    }

    @Transactional
    default <KEY> void deleteByKey(FindByKeyQueryRequirement<Entity, Bean> req) {
        Long count = batchDelete(req);
        if (count > 1) {
            throw new IllegalArgumentException("multiple records deleted when calling deleteByKey");
        }
    }

    Long batchDelete(BasicDelete<Entity> req);

}
